Added methods for ::get_supports_bookmarks(), ::set_bookmarks(),
authorFederico Mena Quintero <federico@ximian.com>
Wed, 8 Oct 2003 04:14:55 +0000 (04:14 +0000)
committerFederico Mena Quintero <federico@src.gnome.org>
Wed, 8 Oct 2003 04:14:55 +0000 (04:14 +0000)
2003-10-07  Federico Mena Quintero  <federico@ximian.com>

* gtkfilesystem.h (struct _GtkFileSystemIface): Added methods for
::get_supports_bookmarks(), ::set_bookmarks(), ::list_bookmarks().
Added a ::bookmarks_changed() signal.

* gtkfilesystem.c (gtk_file_system_get_supports_bookmarks): New function.
(gtk_file_system_set_bookmarks): New function.
(gtk_file_system_list_bookmarks): New function.
(gtk_file_system_base_init): Create the "bookmarks-changed" signal.
(gtk_file_paths_copy): New function.

* gtkfilesystemunix.c (gtk_file_system_unix_get_supports_bookmarks): Implement.
(gtk_file_system_unix_set_bookmarks): Implement.
(gtk_file_system_unix_get_bookmarks): Implement.

* gtkfilesystemgnomevfs.c (struct _GtkFileSystemGnomeVFS): Added
fields for the bookmarks and the GConfClient.
(gtk_file_system_gnome_vfs_set_bookmarks): Implement.
(gtk_file_system_gnome_vfs_list_bookmarks): Implement.

* gtkfilechooserprivate.h (struct _GtkFileChooserIface): Added
methods for ::set_shortcut_folders(), ::list_shortcut_folders().

* gtkfilechooser.c (gtk_file_chooser_set_shortcut_folders): New
function.
(gtk_file_chooser_list_shortcut_folders): New function.

* gtkfilechooserimpldefault.c (create_shortcuts_model): Unref the
old shortcuts model if it exists.  Create the nodes for the
app-specific shortcut folders.
(struct _GtkFileChooserImplDefault): Added a field for the
shortcut_folders.
(gtk_file_chooser_impl_default_set_shortcut_folders): Implement.
(select_shortcuts_folder): New helper function.
(gtk_file_chooser_impl_default_set_current_folder): Use
select_shortcuts_folder().
(shortcuts_append_path): Get the file info here, instead of the
caller.
(shortcuts_append_home): Use shortcuts_append_path().
(shortcuts_append_file_system_roots): Likewise.
(create_shortcuts_model): Add the app-specific shortcut folders
and the bookmarks.
(gtk_file_chooser_impl_default_list_shortcut_folders): Implement.
(create_shortcuts_tree): Added a button to let the user add the
current folder to the bookmarks.
(gtk_file_chooser_impl_default_set_property): Connect to
"bookmarks-changed" on the file system.
(shortcuts_append_bookmarks): New function.

* configure.ac: Depend on GConf.

gtk/gtkfilechooser.c
gtk/gtkfilechooser.h
gtk/gtkfilechooserdefault.c
gtk/gtkfilechooserprivate.h
gtk/gtkfilesystem.c
gtk/gtkfilesystem.h
gtk/gtkfilesystemunix.c

index 0153b23d55412bd5317c76a45d954e16fff4cb7e..c3cd8bf96e5153b53a55c23f650b18c2962179dd 100644 (file)
@@ -1231,3 +1231,40 @@ gtk_file_chooser_get_filter (GtkFileChooser *chooser)
 
   return filter;
 }
+
+/* gtk_file_chooser_set_shortcut_folders:
+ * @chooser: a #GtkFileChooser
+ * @shortcut_folders: a list of #GtkFilePath, or NULL if you want to clear the
+ * current list of shortcut folders.
+ * 
+ * Sets the list of shortcut folders to be shown in a file chooser.  Note that
+ * these do not get saved, as they are provided by the application.  For
+ * example, you can use this to add a "/usr/share/myapp/Clipart" folder to the
+ * volume list.
+ **/
+void
+gtk_file_chooser_set_shortcut_folders (GtkFileChooser *chooser,
+                                      GSList         *shortcut_folders)
+{
+  g_return_if_fail (GTK_IS_FILE_CHOOSER (chooser));
+
+  GTK_FILE_CHOOSER_GET_IFACE (chooser)->set_shortcut_folders (chooser, shortcut_folders);
+}
+
+/**
+ * gtk_file_chooser_list_shortcut_folders:
+ * @chooser: a #GtkFileChooser
+ * 
+ * Queries the list of shortcut folders in the file chooser, as set by
+ * gtk_file_chooser_set_shortcut_folders().
+ * 
+ * Return value: A list of #GtkFilePath, or NULL if there are no shortcut
+ * folders.  You should use gtk_file_paths_free() to free this list.
+ **/
+GSList *
+gtk_file_chooser_list_shortcut_folders (GtkFileChooser *chooser)
+{
+  g_return_val_if_fail (GTK_IS_FILE_CHOOSER (chooser), NULL);
+
+  return GTK_FILE_CHOOSER_GET_IFACE (chooser)->list_shortcut_folders (chooser);
+}
index e2d55c240f961b0436cacf3ec4380900f46136f2..4ee520f06327d56002ca77a63a6a28269a9b3d03 100644 (file)
@@ -121,6 +121,12 @@ void           gtk_file_chooser_set_filter (GtkFileChooser *chooser,
                                           GtkFileFilter  *filter);
 GtkFileFilter *gtk_file_chooser_get_filter (GtkFileChooser *chooser);
 
+/* Per-application shortcut folders */
+
+void    gtk_file_chooser_set_shortcut_folders  (GtkFileChooser *chooser,
+                                               GSList         *shortcut_directories);
+GSList *gtk_file_chooser_list_shortcut_folders (GtkFileChooser *chooser);
+
 G_END_DECLS
 
 #endif /* __GTK_FILE_CHOOSER_H__ */
index fc08b2cc14d1fc577c50ddc1de38896eda2281be..322039cd875c51711a45424d8b5c631333761658 100644 (file)
@@ -73,6 +73,11 @@ struct _GtkFileChooserImplDefault
   GtkFileFilter *current_filter;
   GSList *filters;
 
+  GSList *shortcut_folders;
+
+  guint bookmarks_changed_id;
+  GtkTreeIter bookmarks_iter;
+
   GtkFilePath *current_folder;
   GtkFilePath *preview_path;
 
@@ -84,6 +89,7 @@ struct _GtkFileChooserImplDefault
   GtkWidget *tree;
   GtkWidget *shortcuts_scrollwin;
   GtkWidget *shortcuts_tree;
+  GtkWidget *add_bookmark_button;
   GtkWidget *list_scrollwin;
   GtkWidget *list;
   GtkWidget *entry;
@@ -97,6 +103,7 @@ struct _GtkFileChooserImplDefault
   guint show_hidden : 1;
   guint changing_folder : 1;
   guint list_sort_ascending : 1;
+  guint bookmarks_set : 1;
 };
 
 /* Column numbers for the shortcuts tree */
@@ -136,25 +143,28 @@ static void     gtk_file_chooser_impl_default_get_property (GObject
                                                            GParamSpec            *pspec);
 static void     gtk_file_chooser_impl_default_show_all     (GtkWidget             *widget);
 
-static void           gtk_file_chooser_impl_default_set_current_folder (GtkFileChooser    *chooser,
-                                                                       const GtkFilePath *path);
-static GtkFilePath *  gtk_file_chooser_impl_default_get_current_folder (GtkFileChooser    *chooser);
-static void           gtk_file_chooser_impl_default_set_current_name   (GtkFileChooser    *chooser,
-                                                                       const gchar       *name);
-static void           gtk_file_chooser_impl_default_select_path        (GtkFileChooser    *chooser,
-                                                                       const GtkFilePath *path);
-static void           gtk_file_chooser_impl_default_unselect_path      (GtkFileChooser    *chooser,
-                                                                       const GtkFilePath *path);
-static void           gtk_file_chooser_impl_default_select_all         (GtkFileChooser    *chooser);
-static void           gtk_file_chooser_impl_default_unselect_all       (GtkFileChooser    *chooser);
-static GSList *       gtk_file_chooser_impl_default_get_paths          (GtkFileChooser    *chooser);
-static GtkFilePath *  gtk_file_chooser_impl_default_get_preview_path   (GtkFileChooser    *chooser);
-static GtkFileSystem *gtk_file_chooser_impl_default_get_file_system    (GtkFileChooser    *chooser);
-static void           gtk_file_chooser_impl_default_add_filter         (GtkFileChooser    *chooser,
-                                                                       GtkFileFilter     *filter);
-static void           gtk_file_chooser_impl_default_remove_filter      (GtkFileChooser    *chooser,
-                                                                       GtkFileFilter     *filter);
-static GSList *       gtk_file_chooser_impl_default_list_filters       (GtkFileChooser    *chooser);
+static void           gtk_file_chooser_impl_default_set_current_folder            (GtkFileChooser    *chooser,
+                                                                           const GtkFilePath *path);
+static GtkFilePath *  gtk_file_chooser_impl_default_get_current_folder            (GtkFileChooser    *chooser);
+static void           gtk_file_chooser_impl_default_set_current_name              (GtkFileChooser    *chooser,
+                                                                           const gchar       *name);
+static void           gtk_file_chooser_impl_default_select_path                   (GtkFileChooser    *chooser,
+                                                                           const GtkFilePath *path);
+static void           gtk_file_chooser_impl_default_unselect_path                 (GtkFileChooser    *chooser,
+                                                                           const GtkFilePath *path);
+static void           gtk_file_chooser_impl_default_select_all                    (GtkFileChooser    *chooser);
+static void           gtk_file_chooser_impl_default_unselect_all                  (GtkFileChooser    *chooser);
+static GSList *       gtk_file_chooser_impl_default_get_paths                     (GtkFileChooser    *chooser);
+static GtkFilePath *  gtk_file_chooser_impl_default_get_preview_path              (GtkFileChooser    *chooser);
+static GtkFileSystem *gtk_file_chooser_impl_default_get_file_system               (GtkFileChooser    *chooser);
+static void           gtk_file_chooser_impl_default_add_filter                    (GtkFileChooser    *chooser,
+                                                                           GtkFileFilter     *filter);
+static void           gtk_file_chooser_impl_default_remove_filter                 (GtkFileChooser    *chooser,
+                                                                           GtkFileFilter     *filter);
+static GSList *       gtk_file_chooser_impl_default_list_filters                  (GtkFileChooser    *chooser);
+static void           gtk_file_chooser_impl_default_set_shortcut_folders   (GtkFileChooser    *chooser,
+                                                                           GSList            *shortcut_folders);
+static GSList *       gtk_file_chooser_impl_default_list_shortcut_folders  (GtkFileChooser    *chooser);
 
 static void set_current_filter   (GtkFileChooserImplDefault *impl,
                                  GtkFileFilter             *filter);
@@ -276,6 +286,8 @@ gtk_file_chooser_impl_default_iface_init (GtkFileChooserIface *iface)
   iface->add_filter = gtk_file_chooser_impl_default_add_filter;
   iface->remove_filter = gtk_file_chooser_impl_default_remove_filter;
   iface->list_filters = gtk_file_chooser_impl_default_list_filters;
+  iface->set_shortcut_folders = gtk_file_chooser_impl_default_set_shortcut_folders;
+  iface->list_shortcut_folders = gtk_file_chooser_impl_default_list_shortcut_folders;
 }
 
 static void
@@ -295,6 +307,8 @@ gtk_file_chooser_impl_default_finalize (GObject *object)
 {
   GtkFileChooserImplDefault *impl = GTK_FILE_CHOOSER_IMPL_DEFAULT (object);
 
+  g_signal_handler_disconnect (impl->file_system, impl->bookmarks_changed_id);
+  impl->bookmarks_changed_id = 0;
   g_object_unref (impl->file_system);
 
   G_OBJECT_CLASS (parent_class)->finalize (object);
@@ -331,19 +345,39 @@ set_preview_widget (GtkFileChooserImplDefault *impl,
   update_preview_widget_visibility (impl);
 }
 
-/* Appends a directory to the shortcuts model at the specified iter */
-static void
-shortcuts_append_path (GtkFileChooserImplDefault *impl, GtkTreeIter *iter, GdkPixbuf *pixbuf, const char *label, GtkFilePath *path)
+/* Used from gtk_tree_model_foreach(); selects the item that corresponds to the
+ * current path. */
+static gboolean
+set_current_shortcut_foreach_cb (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
 {
-  GtkFilePath *path_copy;
+  GtkFileChooserImplDefault *impl;
+  GtkFilePath *model_path;
+  GtkTreeSelection *selection;
 
-  path_copy = gtk_file_path_copy (path);
+  impl = GTK_FILE_CHOOSER_IMPL_DEFAULT (data);
 
-  gtk_tree_store_set (impl->shortcuts_model, iter,
-                     SHORTCUTS_COL_PIXBUF, pixbuf,
-                     SHORTCUTS_COL_NAME, label,
-                     SHORTCUTS_COL_PATH, path_copy,
-                     -1);
+  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->shortcuts_tree));
+
+  gtk_tree_model_get (model, iter, SHORTCUTS_COL_PATH, &model_path, -1);
+
+  if (model_path && impl->current_folder && gtk_file_path_compare (model_path, impl->current_folder) == 0)
+    {
+      gtk_tree_selection_select_path (selection, path);
+      return TRUE;
+    }
+  else
+    gtk_tree_selection_unselect_path (selection, path);
+
+  return FALSE;
+}
+
+/* Selects the appropriate node in the shortcuts tree based on the current folder */
+static void
+select_shortcuts_folder (GtkFileChooserImplDefault *impl)
+{
+  gtk_tree_model_foreach (GTK_TREE_MODEL (impl->shortcuts_model),
+                         set_current_shortcut_foreach_cb,
+                         impl);
 }
 
 /* Convenience function to get the display name and icon info for a path */
@@ -371,17 +405,63 @@ get_file_info (GtkFileSystem *file_system, GtkFilePath *path, GError **error)
   return info;
 }
 
+/* Appends a path to the shortcuts tree, making a copy of it.  If parent is
+ * NULL, then the item is appened at the end of the tree.  If the label is NULL,
+ * then the display name of a GtkFileInfo is used.
+ */
+static void
+shortcuts_append_path (GtkFileChooserImplDefault *impl,
+                      GtkTreeIter               *parent,
+                      GtkFilePath               *path,
+                      gboolean                   is_root,
+                      const char                *label)
+{
+  GtkFileInfo *info;
+  GtkFilePath *path_copy;
+  GdkPixbuf *pixbuf;
+  GtkTreeIter iter;
+
+  /* FIXME: what if someone adds a shortcut to a root?  get_file_info() will not
+   * work in that case, I think...
+   */
+
+  if (is_root)
+    info = gtk_file_system_get_root_info (impl->file_system,
+                                         path,
+                                         GTK_FILE_INFO_DISPLAY_NAME | GTK_FILE_INFO_ICON,
+                                         NULL); /* FIXME: Use GError? */
+  else
+    info = get_file_info (impl->file_system, path, NULL); /* FIXME: use GError? */
+
+  if (!info)
+    return;
+
+  pixbuf = gtk_file_info_render_icon (info, impl->shortcuts_tree, ICON_SIZE);
+
+  gtk_tree_store_append (impl->shortcuts_model, &iter, parent);
+  path_copy = gtk_file_path_copy (path);
+
+  if (!label)
+    label = gtk_file_info_get_display_name (info);
+
+  gtk_tree_store_set (impl->shortcuts_model, &iter,
+                     SHORTCUTS_COL_PIXBUF, pixbuf,
+                     SHORTCUTS_COL_NAME, label,
+                     SHORTCUTS_COL_PATH, path_copy,
+                     -1);
+
+  if (pixbuf)
+    g_object_unref (pixbuf);
+}
+
 /* Appends an item for the user's home directory to the shortcuts model */
 static void
 shortcuts_append_home (GtkFileChooserImplDefault *impl)
 {
-  GtkTreeIter iter;
   const char *name;
   const char *home;
   GtkFilePath *home_path;
   char *label;
-  GtkFileInfo *info;
-  GdkPixbuf *pixbuf;
 
   name = g_get_user_name ();
   label = g_strdup_printf ("%s's Home", name);
@@ -389,21 +469,7 @@ shortcuts_append_home (GtkFileChooserImplDefault *impl)
   home = g_get_home_dir ();
   home_path = gtk_file_system_filename_to_path (impl->file_system, home);
 
-  /* FIXME: use GError? */
-  info = get_file_info (impl->file_system, home_path, NULL);
-  if (!info)
-    goto out;
-
-  pixbuf = gtk_file_info_render_icon (info, impl->shortcuts_tree, ICON_SIZE);
-  gtk_file_info_free (info);
-
-  gtk_tree_store_append (impl->shortcuts_model, &iter, NULL);
-  shortcuts_append_path (impl, &iter, pixbuf, label, home_path);
-
-  if (pixbuf)
-    gdk_pixbuf_unref (pixbuf);
-
- out:
+  shortcuts_append_path (impl, NULL, home_path, FALSE, label);
 
   g_free (label);
   gtk_file_path_free (home_path);
@@ -419,52 +485,89 @@ shortcuts_append_file_system_roots (GtkFileChooserImplDefault *impl)
 
   for (l = roots; l; l = l->next)
     {
-      GtkFilePath *path, *path_copy;
-      GtkFileInfo *info;
-      GdkPixbuf *pixbuf;
-      GtkTreeIter iter;
+      GtkFilePath *path;
 
       path = l->data;
-      path_copy = gtk_file_path_copy (path);
-      gtk_file_path_free (path);
+      shortcuts_append_path (impl, NULL, path, TRUE, NULL);
+    }
 
-      info = gtk_file_system_get_root_info (impl->file_system,
-                                           path_copy,
-                                           GTK_FILE_INFO_DISPLAY_NAME | GTK_FILE_INFO_ICON,
-                                           NULL); /* FIXME: Use GError? */
-      if (!info)
-       continue;
+  gtk_file_paths_free (roots);
+}
 
-      pixbuf = gtk_file_info_render_icon (info, impl->shortcuts_tree, ICON_SIZE);
+/* Appends the application-specific shortcut folders to the shortcuts model */
+static void
+shortcuts_append_shortcut_folders (GtkFileChooserImplDefault *impl)
+{
+  GSList *l;
 
-      gtk_tree_store_append (impl->shortcuts_model, &iter, NULL);
-      shortcuts_append_path (impl, &iter, pixbuf, gtk_file_info_get_display_name (info), path_copy);
+  for (l = impl->shortcut_folders; l; l = l->next)
+    {
+      GtkFilePath *path;
 
-      gtk_file_info_free (info);
+      path = l->data;
+      shortcuts_append_path (impl, NULL, path, FALSE, NULL);
+    }
+}
 
-      if (pixbuf)
-       gdk_pixbuf_unref (pixbuf);
+static void
+shortcuts_append_bookmarks (GtkFileChooserImplDefault *impl)
+{
+  GSList *bookmarks, *l;
+
+  if (impl->bookmarks_set)
+    {
+      gtk_tree_store_remove (impl->shortcuts_model, &impl->bookmarks_iter);
+      impl->bookmarks_set = FALSE;
     }
 
-  g_slist_free (roots);
+  if (!gtk_file_system_get_supports_bookmarks (impl->file_system))
+    return;
+
+  gtk_tree_store_append (impl->shortcuts_model, &impl->bookmarks_iter, NULL);
+  gtk_tree_store_set (impl->shortcuts_model, &impl->bookmarks_iter,
+                     SHORTCUTS_COL_PIXBUF, NULL, /* FIXME: use a nice icon */
+                     SHORTCUTS_COL_NAME, "Bookmarks",
+                     SHORTCUTS_COL_PATH, NULL,
+                     -1);
+  impl->bookmarks_set = TRUE;
+
+  bookmarks = gtk_file_system_list_bookmarks (impl->file_system);
+
+  for (l = bookmarks; l; l = l->next)
+    {
+      GtkFilePath *path;
+
+      path = l->data;
+      shortcuts_append_path (impl, &impl->bookmarks_iter, path, FALSE, NULL);
+    }
+
+  gtk_tree_view_expand_all (GTK_TREE_VIEW (impl->shortcuts_tree));
+
+  select_shortcuts_folder (impl);
 }
 
 /* Creates the GtkTreeStore used as the shortcuts model */
 static void
 create_shortcuts_model (GtkFileChooserImplDefault *impl)
 {
-  g_assert (impl->shortcuts_model == NULL);
+  if (impl->shortcuts_model)
+    g_object_unref (impl->shortcuts_model);
 
   impl->shortcuts_model = gtk_tree_store_new (SHORTCUTS_COL_NUM_COLUMNS,
                                              GDK_TYPE_PIXBUF,  /* pixbuf */
                                              G_TYPE_STRING,    /* name */
                                              G_TYPE_POINTER);  /* path */
 
-  if (!impl->file_system)
-    return;
+  if (impl->file_system)
+    {
+      shortcuts_append_home (impl);
+      shortcuts_append_file_system_roots (impl);
+      shortcuts_append_shortcut_folders (impl);
+      shortcuts_append_bookmarks (impl);
+    }
 
-  shortcuts_append_home (impl);
-  shortcuts_append_file_system_roots (impl);
+  gtk_tree_view_set_model (GTK_TREE_VIEW (impl->shortcuts_tree), GTK_TREE_MODEL (impl->shortcuts_model));
+  select_shortcuts_folder (impl);
 }
 
 /* Creates the widgets for the filter option menu */
@@ -513,7 +616,9 @@ create_folder_tree (GtkFileChooserImplDefault *impl)
                                  GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
   gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (impl->tree_scrollwin),
                                       GTK_SHADOW_IN);
+#if 0
   gtk_widget_show (impl->tree_scrollwin);
+#endif
 
   /* Tree */
 
@@ -548,14 +653,36 @@ create_folder_tree (GtkFileChooserImplDefault *impl)
   return impl->tree_scrollwin;
 }
 
+/* Callback used when the "Add bookmark" button is clicked */
+static void
+add_bookmark_button_clicked_cb (GtkButton *button,
+                               GtkFileChooserImplDefault *impl)
+{
+  GSList *bookmarks;
+
+  if (!gtk_file_system_get_supports_bookmarks (impl->file_system))
+    return;
+
+  bookmarks = gtk_file_system_list_bookmarks (impl->file_system);
+  bookmarks = g_slist_append (bookmarks, gtk_file_path_copy (impl->current_folder));
+
+  gtk_file_system_set_bookmarks (impl->file_system, bookmarks, NULL); /* FIXME: use GError */
+
+  gtk_file_paths_free (bookmarks);
+}
+
 /* Creates the widgets for the shortcuts and bookmarks tree */
 static GtkWidget *
 create_shortcuts_tree (GtkFileChooserImplDefault *impl)
 {
+  GtkWidget *vbox;
   GtkTreeSelection *selection;
   GtkTreeViewColumn *column;
   GtkCellRenderer *renderer;
 
+  vbox = gtk_vbox_new (FALSE, 12);
+  gtk_widget_show (vbox);
+
   /* Scrolled window */
 
   impl->shortcuts_scrollwin = gtk_scrolled_window_new (NULL, NULL);
@@ -563,6 +690,7 @@ create_shortcuts_tree (GtkFileChooserImplDefault *impl)
                                  GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
   gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (impl->shortcuts_scrollwin),
                                       GTK_SHADOW_IN);
+  gtk_box_pack_start (GTK_BOX (vbox), impl->shortcuts_scrollwin, TRUE, TRUE, 0);
   gtk_widget_show (impl->shortcuts_scrollwin);
 
   /* Tree */
@@ -580,7 +708,6 @@ create_shortcuts_tree (GtkFileChooserImplDefault *impl)
   /* Model */
 
   create_shortcuts_model (impl);
-  gtk_tree_view_set_model (GTK_TREE_VIEW (impl->shortcuts_tree), GTK_TREE_MODEL (impl->shortcuts_model));
 
   /* Column */
 
@@ -588,7 +715,7 @@ create_shortcuts_tree (GtkFileChooserImplDefault *impl)
   gtk_tree_view_column_set_title (column, "Folder");
 
   renderer = gtk_cell_renderer_pixbuf_new ();
-  gtk_tree_view_column_pack_start (column, renderer, TRUE);
+  gtk_tree_view_column_pack_start (column, renderer, FALSE);
   gtk_tree_view_column_set_attributes (column, renderer,
                                       "pixbuf", 0,
                                       NULL);
@@ -601,7 +728,17 @@ create_shortcuts_tree (GtkFileChooserImplDefault *impl)
 
   gtk_tree_view_append_column (GTK_TREE_VIEW (impl->shortcuts_tree), column);
 
-  return impl->shortcuts_scrollwin;
+  /* Button */
+
+  impl->add_bookmark_button = gtk_button_new_with_label ("Add bookmark");
+  g_signal_connect (impl->add_bookmark_button, "clicked",
+                   G_CALLBACK (add_bookmark_button_clicked_cb), impl);
+  gtk_box_pack_end (GTK_BOX (vbox), impl->add_bookmark_button, FALSE, FALSE, 0);
+
+  if (gtk_file_system_get_supports_bookmarks (impl->file_system))
+    gtk_widget_show (impl->add_bookmark_button);
+
+  return vbox;
 }
 
 /* Creates the widgets for the folder tree */
@@ -822,6 +959,14 @@ set_extra_widget (GtkFileChooserImplDefault *impl,
     }
 }
 
+/* Callback used when the set of bookmarks changes in the file system */
+static void
+bookmarks_changed_cb (GtkFileSystem             *file_system,
+                     GtkFileChooserImplDefault *impl)
+{
+  shortcuts_append_bookmarks (impl);
+}
+
 static void
 gtk_file_chooser_impl_default_set_property (GObject         *object,
                                            guint            prop_id,
@@ -842,10 +987,19 @@ gtk_file_chooser_impl_default_set_property (GObject         *object,
        if (impl->file_system != file_system)
          {
            if (impl->file_system)
-             g_object_unref (impl->file_system);
+             {
+               g_signal_handler_disconnect (impl->file_system, impl->bookmarks_changed_id);
+               impl->bookmarks_changed_id = 0;
+               g_object_unref (impl->file_system);
+             }
            impl->file_system = file_system;
            if (impl->file_system)
-             g_object_ref (impl->file_system);
+             {
+               g_object_ref (impl->file_system);
+               impl->bookmarks_changed_id = g_signal_connect (impl->file_system, "bookmarks-changed",
+                                                              G_CALLBACK (bookmarks_changed_cb),
+                                                              impl);
+             }
          }
       }
       break;
@@ -984,32 +1138,6 @@ expand_and_select_func (GtkFileSystemModel *model,
   gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (impl->tree), path, NULL, TRUE, 0.3, 0.5);
 }
 
-/* Used from gtk_tree_model_foreach(); selects the item that corresponds to the
- * current path. */
-static gboolean
-set_current_shortcut_foreach_cb (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
-{
-  GtkFileChooserImplDefault *impl;
-  GtkFilePath *model_path;
-  GtkTreeSelection *selection;
-
-  impl = GTK_FILE_CHOOSER_IMPL_DEFAULT (data);
-
-  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->shortcuts_tree));
-
-  gtk_tree_model_get (model, iter, SHORTCUTS_COL_PATH, &model_path, -1);
-
-  if (model_path && impl->current_folder && gtk_file_path_compare (model_path, impl->current_folder) == 0)
-    {
-      gtk_tree_selection_select_path (selection, path);
-      return TRUE;
-    }
-  else
-    gtk_tree_selection_unselect_path (selection, path);
-
-  return FALSE;
-}
-
 static void
 gtk_file_chooser_impl_default_set_current_folder (GtkFileChooser    *chooser,
                                                  const GtkFilePath *path)
@@ -1019,13 +1147,8 @@ gtk_file_chooser_impl_default_set_current_folder (GtkFileChooser    *chooser,
   _gtk_file_system_model_path_do (impl->tree_model, path,
                                  expand_and_select_func, impl);
 
-  /* Select the appropriate item in the shortcuts tree if there is an item that
-   * matches the selected path.
-   */
   if (!impl->changing_folder)
-    gtk_tree_model_foreach (GTK_TREE_MODEL (impl->shortcuts_model),
-                           set_current_shortcut_foreach_cb,
-                           impl);
+    select_shortcuts_folder (impl);
 }
 
 static GtkFilePath *
@@ -1307,6 +1430,26 @@ gtk_file_chooser_impl_default_list_filters (GtkFileChooser *chooser)
   return g_slist_copy (impl->filters);
 }
 
+static void
+gtk_file_chooser_impl_default_set_shortcut_folders (GtkFileChooser *chooser,
+                                                   GSList         *shortcut_folders)
+{
+  GtkFileChooserImplDefault *impl = GTK_FILE_CHOOSER_IMPL_DEFAULT (chooser);
+
+  gtk_file_paths_free (impl->shortcut_folders);
+  impl->shortcut_folders = gtk_file_paths_copy (shortcut_folders);
+
+  create_shortcuts_model (impl);
+}
+
+static GSList *
+gtk_file_chooser_impl_default_list_shortcut_folders (GtkFileChooser *chooser)
+{
+  GtkFileChooserImplDefault *impl = GTK_FILE_CHOOSER_IMPL_DEFAULT (chooser);
+
+  return gtk_file_paths_copy (impl->shortcut_folders);
+}
+
 static gboolean
 list_model_filter_func (GtkFileSystemModel *model,
                        GtkFilePath        *path,
index aeb79ee89d8835a7edca82997c55ccf07bd9ec56..9f0361896a19e34059101057ef71cb6285e191ad 100644 (file)
@@ -36,33 +36,35 @@ struct _GtkFileChooserIface
 
   /* Methods
    */
-  void           (*set_current_folder) (GtkFileChooser    *chooser,
-                                       const GtkFilePath *path);
-  GtkFilePath *  (*get_current_folder) (GtkFileChooser    *chooser);
-  void           (*set_current_name)   (GtkFileChooser    *chooser,
-                                       const gchar       *name);
-  void           (*select_path)        (GtkFileChooser    *chooser,
-                                       const GtkFilePath *path);
-  void           (*unselect_path)      (GtkFileChooser    *chooser,
-                                       const GtkFilePath *path);
-  void           (*select_all)         (GtkFileChooser    *chooser);
-  void           (*unselect_all)       (GtkFileChooser    *chooser);
-  GSList *       (*get_paths)          (GtkFileChooser    *chooser);
-  GtkFilePath *  (*get_preview_path)   (GtkFileChooser    *chooser);
-  GtkFileSystem *(*get_file_system)    (GtkFileChooser    *chooser);
-  void           (*add_filter)         (GtkFileChooser    *chooser,
-                                       GtkFileFilter     *filter);
-  void           (*remove_filter)      (GtkFileChooser    *chooser,
-                                       GtkFileFilter     *filter);
-  GSList *       (*list_filters)       (GtkFileChooser    *chooser);
-
+  void           (*set_current_folder)            (GtkFileChooser    *chooser,
+                                           const GtkFilePath *path);
+  GtkFilePath *  (*get_current_folder)            (GtkFileChooser    *chooser);
+  void           (*set_current_name)              (GtkFileChooser    *chooser,
+                                           const gchar       *name);
+  void           (*select_path)                   (GtkFileChooser    *chooser,
+                                           const GtkFilePath *path);
+  void           (*unselect_path)                 (GtkFileChooser    *chooser,
+                                           const GtkFilePath *path);
+  void           (*select_all)                    (GtkFileChooser    *chooser);
+  void           (*unselect_all)                  (GtkFileChooser    *chooser);
+  GSList *       (*get_paths)                     (GtkFileChooser    *chooser);
+  GtkFilePath *  (*get_preview_path)              (GtkFileChooser    *chooser);
+  GtkFileSystem *(*get_file_system)               (GtkFileChooser    *chooser);
+  void           (*add_filter)                    (GtkFileChooser    *chooser,
+                                           GtkFileFilter     *filter);
+  void           (*remove_filter)                 (GtkFileChooser    *chooser,
+                                           GtkFileFilter     *filter);
+  GSList *       (*list_filters)                  (GtkFileChooser    *chooser);
+  void           (*set_shortcut_folders)   (GtkFileChooser    *chooser,
+                                           GSList            *bookmarks);
+  GSList *       (*list_shortcut_folders)  (GtkFileChooser    *chooser);
   
   /* Signals
    */
   void (*current_folder_changed) (GtkFileChooser *chooser);
   void (*selection_changed)      (GtkFileChooser *chooser);
   void (*update_preview)         (GtkFileChooser *chooser);
-  void (*file_activated)         (GtkFileChooser *chooser); 
+  void (*file_activated)         (GtkFileChooser *chooser);
 };
 
 GtkFileSystem *_gtk_file_chooser_get_file_system         (GtkFileChooser    *chooser);
index a7a7be53f66f77278a15760d7fb93ba73e5a2865..82f974dc244720bc333da7bfe86e3176e9d3396b 100644 (file)
@@ -448,6 +448,13 @@ gtk_file_system_base_init (gpointer g_class)
                    NULL, NULL,
                    g_cclosure_marshal_VOID__VOID,
                    G_TYPE_NONE, 0);
+      g_signal_new ("bookmarks-changed",
+                   iface_type,
+                   G_SIGNAL_RUN_LAST,
+                   G_STRUCT_OFFSET (GtkFileSystemIface, bookmarks_changed),
+                   NULL, NULL,
+                   g_cclosure_marshal_VOID__VOID,
+                   G_TYPE_NONE, 0);
 
       initialized = TRUE;
     }
@@ -644,6 +651,68 @@ gtk_file_system_filename_to_path (GtkFileSystem *file_system,
   return GTK_FILE_SYSTEM_GET_IFACE (file_system)->filename_to_path (file_system, filename);
 }
 
+/**
+ * gtk_file_system_get_supports_bookmarks:
+ * @chooser: a #GtkFileSystem
+ * 
+ * Queries whether the file system supports the bookmarks feature.  If this
+ * returns FALSE, then gtk_file_system_set_bookmarks() and
+ * gtk_file_system_list_bookmarks() will do nothing.
+ * 
+ * Return value: TRUE if the file system supports bookmarks, FALSE otherwise.
+ **/
+gboolean
+gtk_file_system_get_supports_bookmarks (GtkFileSystem *file_system)
+{
+  g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), FALSE);
+
+  return GTK_FILE_SYSTEM_GET_IFACE (file_system)->get_supports_bookmarks (file_system);
+}
+
+/**
+ * gtk_file_system_set_bookmarks:
+ * @file_system: a #GtkFileSystem
+ * @bookmarks: a list of #GtkFilePath, or NULL if you want to clear the current
+ * list of bookmarks.
+ * @error: location to store error, or %NULL.
+ * 
+ * Sets the list of bookmarks to be stored by a file system.  This will also
+ * cause the bookmarks list to get saved.  The ::bookmarks_changed signal will
+ * be emitted.  Normally you do not need to call this function.
+ *
+ * See also: gtk_file_system_get_supports_bookmarks()
+ **/
+void
+gtk_file_system_set_bookmarks (GtkFileSystem *file_system,
+                              GSList        *bookmarks,
+                              GError       **error)
+{
+  g_return_if_fail (GTK_IS_FILE_SYSTEM (file_system));
+  g_return_if_fail (gtk_file_system_get_supports_bookmarks (file_system));
+
+  GTK_FILE_SYSTEM_GET_IFACE (file_system)->set_bookmarks (file_system, bookmarks, error);
+}
+
+/**
+ * gtk_file_system_list_bookmarks:
+ * @file_system: a #GtkFileSystem
+ * 
+ * Queries the list of bookmarks in the file system.
+ * 
+ * Return value: A list of #GtkFilePath, or NULL if there are no configured
+ * bookmarks.  You should use gtk_file_paths_free() to free this list.
+ *
+ * See also: gtk_file_system_get_supports_bookmarks()
+ **/
+GSList *
+gtk_file_system_list_bookmarks (GtkFileSystem *file_system)
+{
+  g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL);
+  g_return_val_if_fail (gtk_file_system_get_supports_bookmarks (file_system), NULL);
+
+  return GTK_FILE_SYSTEM_GET_IFACE (file_system)->list_bookmarks (file_system);
+}
+
 /*****************************************
  *             GtkFileFolder             *
  *****************************************/
@@ -756,6 +825,42 @@ gtk_file_paths_sort (GSList *paths)
   return g_slist_sort (paths, (GCompareFunc)strcmp);
 }
 
+/**
+ * gtk_file_paths_copy:
+ * @paths: A #GSList of 3GtkFilePath structures.
+ * 
+ * Copies a list of #GtkFilePath structures.
+ * 
+ * Return value: A copy of @paths.  Since the contents of the list are copied as
+ * well, you should use gtk_file_paths_free() to free the result.
+ **/
+GSList *
+gtk_file_paths_copy (GSList *paths)
+{
+  GSList *head, *tail, *l;
+
+  head = tail = NULL;
+
+  for (l = paths; l; l = l->next)
+    {
+      GtkFilePath *path;
+      GSList *node;
+
+      path = l->data;
+      node = g_slist_alloc ();
+
+      if (tail)
+       tail->next = node;
+      else
+       head = node;
+
+      node->data = gtk_file_path_copy (path);
+      tail = node;
+    }
+
+  return head;
+}
+
 void
 gtk_file_paths_free (GSList *paths)
 {
index f57616369caac1c43245b9aeeba832d957296713..8eefad487b3d8858a506414c8ee06a96540f4ffe 100644 (file)
@@ -176,9 +176,18 @@ struct _GtkFileSystemIface
   GtkFilePath *(*filename_to_path) (GtkFileSystem      *file_system,
                                    const gchar        *path);
 
+  /* Bookmarks */
+
+  gboolean       (*get_supports_bookmarks) (GtkFileSystem *file_system);
+  void           (*set_bookmarks)          (GtkFileSystem *file_system,
+                                           GSList        *bookmarks,
+                                           GError       **error);
+  GSList *       (*list_bookmarks)         (GtkFileSystem *file_system);
+
   /* Signals
    */
-  void (*roots_changed) (GtkFileSystem *file_system);
+  void (*roots_changed)     (GtkFileSystem *file_system);
+  void (*bookmarks_changed) (GtkFileSystem *file_system);
 };
 
 GType             gtk_file_system_get_type       (void);
@@ -227,6 +236,14 @@ GtkFilePath *gtk_file_system_uri_to_path      (GtkFileSystem     *file_system,
 GtkFilePath *gtk_file_system_filename_to_path (GtkFileSystem     *file_system,
                                               const gchar       *filename);
 
+gboolean gtk_file_system_get_supports_bookmarks (GtkFileSystem *file_system);
+
+void    gtk_file_system_set_bookmarks  (GtkFileSystem *file_system,
+                                       GSList        *bookmarks,
+                                       GError       **error);
+GSList *gtk_file_system_list_bookmarks (GtkFileSystem *file_system);
+
+
 /*
  * Detailed information about a particular folder
  */
@@ -290,6 +307,7 @@ GtkFileInfo *gtk_file_folder_get_info      (GtkFileFolder      *folder,
                                                   gtk_file_path_get_string (path2))
 
 GSList *gtk_file_paths_sort (GSList *paths);
+GSList *gtk_file_paths_copy (GSList *paths);
 void    gtk_file_paths_free (GSList *paths);
 
 G_END_DECLS
index a2a9c9b200ab5a55a28f1e872103d1bc5763ddcb..f62f44e1c57e686b10ba096648a186dac6a286ac 100644 (file)
@@ -112,6 +112,12 @@ static GtkFilePath *gtk_file_system_unix_uri_to_path      (GtkFileSystem     *fi
 static GtkFilePath *gtk_file_system_unix_filename_to_path (GtkFileSystem     *file_system,
                                                           const gchar       *filename);
 
+static gboolean       gtk_file_system_unix_get_supports_bookmarks (GtkFileSystem *file_system);
+static void           gtk_file_system_unix_set_bookmarks          (GtkFileSystem *file_system,
+                                                                  GSList        *bookmarks,
+                                                                  GError       **error);
+static GSList *       gtk_file_system_unix_list_bookmarks         (GtkFileSystem *file_system);
+
 static GType gtk_file_folder_unix_get_type   (void);
 static void  gtk_file_folder_unix_class_init (GtkFileFolderUnixClass *class);
 static void  gtk_file_folder_unix_iface_init (GtkFileFolderIface     *iface);
@@ -213,6 +219,9 @@ gtk_file_system_unix_iface_init   (GtkFileSystemIface *iface)
   iface->path_to_filename = gtk_file_system_unix_path_to_filename;
   iface->uri_to_path = gtk_file_system_unix_uri_to_path;
   iface->filename_to_path = gtk_file_system_unix_filename_to_path;
+  iface->get_supports_bookmarks = gtk_file_system_unix_get_supports_bookmarks;
+  iface->set_bookmarks = gtk_file_system_unix_set_bookmarks;
+  iface->list_bookmarks = gtk_file_system_unix_list_bookmarks;
 }
 
 static void
@@ -532,6 +541,29 @@ gtk_file_system_unix_filename_to_path (GtkFileSystem *file_system,
   return gtk_file_path_new_dup (filename);
 }
 
+static gboolean
+gtk_file_system_unix_get_supports_bookmarks (GtkFileSystem *file_system)
+{
+  return FALSE;
+}
+
+static void
+gtk_file_system_unix_set_bookmarks (GtkFileSystem *file_system,
+                                   GSList        *bookmarks,
+                                   GError       **error)
+{
+  g_set_error (error,
+              GTK_FILE_SYSTEM_ERROR,
+              GTK_FILE_SYSTEM_ERROR_FAILED,
+              "This file system does not support bookmarks"); 
+}
+
+static GSList *
+gtk_file_system_unix_list_bookmarks (GtkFileSystem *file_system)
+{
+  return NULL;
+}
+
 /*
  * GtkFileFolderUnix
  */